﻿using FluentFTP;
using HAF.FtpUtility;
using HAF.LogUtility;
using Iptv.UploadResourceItem.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Iptv.UploadResourceItem.Helper
{
    /// <summary>
    /// 
    /// </summary>
    public class MediaUploader: PushMessageable, IDisposable
    {
        string _remoteUrl = string.Empty;
        string _localPath = string.Empty;
        string _correlateId = string.Empty;
        int _cacheSize = 3;
        /// <summary>
        /// 任务结束异步事件
        /// </summary>
        public Action<string, bool, string> UploadTaskEndEvent;
        /// <summary>
        /// 任务状态更新
        /// </summary>
        public Action<string, EnumUploadTaskStatus, int> UpdateUploadTaskStat;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="ftpurl"></param>
        /// <param name="filepath"></param>
        /// <param name="buffer"></param>
        public MediaUploader(string ftpurl, string filepath, int buffer)
        {
            _remoteUrl = ftpurl;
            _localPath = filepath;
            _cacheSize = buffer;
        }
        /// <summary>
        /// 析构函数
        /// </summary>
        public void Dispose()
        {
            ShowDebugMessage("任务[{0}]完成", _remoteUrl);
        }

        /// <summary>
        /// 启动上传
        /// </summary>
        public void Run(string correlateId)
        {
            _correlateId = correlateId;
            try
            {
                var tmpSiteParams = FtpUrlParser.ParseFtpUrl(_remoteUrl);
                if (tmpSiteParams != null)
                {
                    ShowInfoMessageExt(correlateId, "开始上传文件{0}", _remoteUrl);

                    UpdateUploadTaskStat?.Invoke(correlateId, EnumUploadTaskStatus.Exec, 2);
                    
                    //启动下载
                    using (FluentFtpHelper ftpClien = new FluentFtpHelper(tmpSiteParams))
                    {
                        ftpClien.LogOutName = correlateId;
                        ftpClien.BufferSize = _cacheSize;
                        ftpClien.WriteConsoleMessageEvent = WriteConsoleMessageEvent;
                        ftpClien.UploadProgressChangeEvent = GatherAverageFlow;
                        //ftpClien.ReportMessageEvent = PushLog;
                        ftpClien.UploadEndEvent = UploadTaskEnd;

                        ftpClien.UploadFile(_localPath, tmpSiteParams.FileSets[0].RemoteRootDirectory, correlateId);
                    };
                }
                else
                {
                    UpdateUploadTaskStat?.Invoke(correlateId, EnumUploadTaskStatus.Error, 0);
                    ShowErrMessageExt(correlateId, "任务解析失败 {0}", _remoteUrl);
                }
            }
            catch (Exception ex)
            {
                UpdateUploadTaskStat?.Invoke(correlateId, EnumUploadTaskStatus.Error, 0);
                WriteErrMessageExt(correlateId, ex.ToString());
            }
        }

        private void UploadTaskEnd(string tid, bool stat, string message = "")
        {
            if (stat)
            {
                _averageSpeed = (_minSpeed + _maxSpeed) / 2;
                ShowDebugMessageExt(tid, string.Format("本次上传工作完成，最小速率为{0}，最大速率为{1}，平均速率为{2}", GetFlowSpeed(_minSpeed), GetFlowSpeed(_maxSpeed), GetFlowSpeed(_averageSpeed)));
            }

            UploadTaskEndEvent?.Invoke(tid, stat, string.Concat(message, " speed ", GetFlowSpeedShort(_averageSpeed)));

            //ShowDebugMessageExt(tid, "文件上传任务结束 状态为[{0}]", stat);
        }

        double _maxSpeed = 0;
        double _minSpeed = 0;
        double _averageSpeed = 1024;
        int iProcess = 0;
        List<RunProgress> progressLst = new List<RunProgress>();
        private void GatherAverageFlow(FtpProgress progress)
        {
            //初始化速度值
            if (_minSpeed == 0)
            {
                _minSpeed = progress.TransferSpeed;
                _maxSpeed = progress.TransferSpeed;
            }
            if (progress.TransferSpeed < _minSpeed && progress.TransferSpeed > 1024)
            {
                //ShowDebugMessage(string.Format("上传最小速率变化 {0} => {1}", _minSpeed, progress.TransferSpeed));
                _minSpeed = progress.TransferSpeed;
            }
            if (progress.TransferSpeed > _maxSpeed)
            {
                //ShowDebugMessage(string.Format("上传最大速率变化 {0} => {1}", _maxSpeed, progress.TransferSpeed));
                _maxSpeed = progress.TransferSpeed;
            }

            //MaxValue = flowsize > MaxValue ? flowsize : MaxValue;
            //MinValue = flowsize < MinValue ? flowsize : MinValue;
            //string flowStr = flowsize > 1024 * 1024 ? string.Format("{0}MB/s", Math.Round((double)flowsize / (1024 * 1024), 2)) : string.Format("{0}KB/s", Math.Round((double)flowsize / 1024, 2));
            //bool report = false;
            int iOut = (int)progress.Progress;
            if (progress.Progress > 1 && iOut % 4 == 0)
            {
                if (iProcess < iOut)
                {
                    UpdateUploadTaskStat?.Invoke(_correlateId, EnumUploadTaskStatus.Exec, iOut);
                    iProcess = iOut;
                }
            }
        }

        private string GetFlowSpeed(double speed)
        {
            return speed > 1024 * 1024 ? string.Format("{0}MB/s [{1}]", Math.Round((double)speed / (1024 * 1024), 2), speed) : string.Format("{0}KB/s [{1}]", Math.Round((double)speed / 1024, 2), speed);
        }

        private string GetFlowSpeedShort(double speed)
        {
            return speed > 1024 * 1024 ? string.Format("{0}MB/s", Math.Round((double)speed / (1024 * 1024), 2)) : string.Format("{0}KB/s", Math.Round((double)speed / 1024, 2));
        }
    }
}
